#include "StdAfx.h"
#include "IdentifyLandmarks.h"

//////////////////////////////////////////////////////////////////////////
//Author	:	Ross Conroy ross.conroy@tees.ac.uk
//Date		:	07/10/2014
//
//This class is used to identify landmarks in data using and of the
//following
//-Reset Actions
//-Unique Observations
//-Zero History Actions
//////////////////////////////////////////////////////////////////////////
IdentifyLandmarks::IdentifyLandmarks(void)
{
}

//////////////////////////////////////////////////////////////////////////
//Extracts rows from data before passing it onto reset actions for processing
//////////////////////////////////////////////////////////////////////////
void IdentifyLandmarks::ResetActions(string inputFile, string outputFile, list<string> resetActions, string stateCol, string obsCol, string actionCol)
{
	DataRowFile dataRowFile;
	list<DataRow> rows = dataRowFile.FileToRows(inputFile, stateCol, obsCol, actionCol);
	ResetActions(rows, resetActions);
}

//////////////////////////////////////////////////////////////////////////
//Loops though all actions in the data for and that are reset actions
//and marks them as landmarks
//////////////////////////////////////////////////////////////////////////
list<DataRow> IdentifyLandmarks::ResetActions(list<DataRow> dataRows, list<string> resetActions)
{
	for (list<DataRow>::iterator it = dataRows.begin(); it != dataRows.end(); it++)
	{
		DataRow row = *it;

		for(list<string>::iterator its = resetActions.begin(); its != resetActions.end(); its++)
		{
			string action = *its;
			if(row.action == action)
			{
				row.isLandmark == true;
			}
		}
	}

	return dataRows;
}

//////////////////////////////////////////////////////////////////////////
//Extracts rows from data before passing it onto unique state for processing
//////////////////////////////////////////////////////////////////////////
void IdentifyLandmarks::UniqueState(string inputFile, string outputFile, string stateCol, string obsCol, string actionCol)
{
	DataRowFile dataRowFile;
	list<DataRow> rows = dataRowFile.FileToRows(inputFile, stateCol, obsCol, actionCol);
	UniqueState(rows);
}

//////////////////////////////////////////////////////////////////////////
//loops through all of the state and observations looking for unique
//state observation pairs and marks them as landmarks.
//unique pairs are ones where the state only results in the observation
//and the observation only originates from the state
//////////////////////////////////////////////////////////////////////////
list<DataRow> IdentifyLandmarks::UniqueState(list<DataRow> dataRows)
{
	return dataRows;
}

//////////////////////////////////////////////////////////////////////////
//Extracts rows from data before passing it onto zero history for processing
//////////////////////////////////////////////////////////////////////////
void IdentifyLandmarks::ZeroHistoryAction(string inputFile, string outputFile, string stateCol, string obsCol, string actionCol, int maxHistory)
{
	DataRowFile dataRowFile;
	list<DataRow> rows = dataRowFile.FileToRows(inputFile, stateCol, obsCol, actionCol);
	rows = ZeroHistoryAction(rows, maxHistory);
	dataRowFile.RowsToFile(outputFile, rows, stateCol, obsCol, actionCol);
}

//////////////////////////////////////////////////////////////////////////
//Looks at each action trying to identify the history for each, any
//that clearly have no history are marked as landmarks
//////////////////////////////////////////////////////////////////////////
list<DataRow> IdentifyLandmarks::ZeroHistoryAction(list<DataRow> dataRows, int maxHistory)
{
	for(list<DataRow>::iterator itd = dataRows.begin(); itd != dataRows.end(); itd++)
	{
		int maxHistorySize = 0;

		//for each history length check number of matches and same actions in data
		for(int hs = 0; hs < maxHistory; hs++)
		{
			int tempH = hs;
			DataRow currentRow = *itd;
			list<DataRow> history;
			bool landmarkFound = false;
			for(list<DataRow>::iterator itdr = itd; (itdr != dataRows.begin()) && (tempH >= 0) && !landmarkFound; itdr--)
			{	
				history.push_front(*itdr);

				if(itdr->isLandmark)
				{
					landmarkFound = true;
				}
				tempH --;
			}

			int historyCount = 0;
			int historyActionCount = 0;

			for(list<DataRow>::iterator itdh = dataRows.begin(); itdh != dataRows.end(); itdh++)
			{
				tempH = hs;
				bool tempLandmarkFound = false;
				list<DataRow> tempHistory;				
				for(list<DataRow>::iterator itdr = itdh; (itdr!= dataRows.begin()) && (tempH >= 0) && !tempLandmarkFound; itdr--)
				{	
					tempHistory.push_front(*itdr);

					if(itdr->isLandmark)
					{
						tempLandmarkFound = true;
					}
					tempH --;
				}

				//Both histories must be same length
				int currentHistItem = 0;
				if(tempHistory.size() == history.size())
				{
					bool matchHist = true;
					bool matchAction = true;

					list<DataRow>::iterator itth = tempHistory.begin();
					for(list<DataRow>::iterator ith = history.begin(); ith != history.end() && matchHist; ith++)
					{
						DataRow currHistRow = *ith;
						DataRow currTempHistRow = *itth;

						//Only interested in action on first step of history so only allow observation checks when not 0
						if(currentHistItem != 0)
						{
							if(currHistRow.observation != currTempHistRow.observation)
							{
								matchHist = false;
							}
						}

						//only use action in final if not the final history item to check
						if(currentHistItem != hs)
						{
							if(currentRow.action != currTempHistRow.action)
							{
								matchHist = false;
							}
						}
						else
						{
							//Keep a record of is the last actions matched used for later calculations
							if(currentRow.action != currTempHistRow.action)
							{
								matchAction = false;
							}
							else
							{
								matchAction = true;
							}
						}

						currentHistItem ++;
						itth ++;
					}

					//if histories match, finally check final action in each history for a match
					if(matchHist)
					{
						historyCount ++;
						if(matchAction)
						{
							historyActionCount ++;
						}
					}
				}

				//Compare ratio of history occurrences and action outcomes
				if((historyCount > 1) && (historyActionCount > 1))
				{
					if(historyCount == historyActionCount)
					{
						maxHistorySize = hs;
					}
				}
			}
		}

		if(maxHistorySize == 0)
		{
			itd->isLandmark = true;
		}
		else
		{
			itd->isLandmark = false;
		}

		itd->historyLength = maxHistorySize;
	}


	return dataRows;
}